Generated code - Databinding with ASP.NET webforms, SelfServicing
Preface
In ASP.NET web forms, databinding is fully 2-way, and can be setup
declaratively, which means you can setup databinding completely in HTML,
without the necessity of code in the code-behind file. This section is about
databinding with a set of data using a
DataSource control.
LLBLGen Pro datasource controls
The LLBLGen Pro runtime framework ships with its own DataSourceControl
controls:
LLBLGenProDataSource for selfservicing and
LLBLGenProDataSource2 for adapter. These also are located in the
SD.LLBLGen.Pro.ORMSupportClasses.Web dll. To use them at design time,
you have to add them to the toolbox first. This can be done manually by
right-clicking the toolbox when a web form is open in the VS.NET editor
(HTML or design view) and then by selecting 'Choose items...' which allows
you to browse to the SD.LLBLGen.Pro.ORMSupportClasses.Web dll.
Getting started with the LLBLGenProDataSource control
Dragging the datasource control of choice onto a form in design mode will show you the smart tag to configure the datasource. The
LLBLGenProDataSource control can be used for an entity collection, TypedList or TypedView.
It's recommended you use the smart-tag to setup the
LLBLGenProDataSource
control. To learn more about the specific properties of the
LLBLGenProDataSource
control, please consult the
LLBLGen Pro reference manual for the
LLBLGenProDataSource control.
The
LLBLGenProDataSource control accepts a type specification which is used for the particular container type: so
the type of the entity collection, the type of a TypedList or the type of a
TypedView. The container type, thus what kind of object is contained
in the
LLBLGenProDataSource control, is specified using the property
DataContainerType, accessable in the designer for the
LLBLGenProDataSource control
and also in the property grid of VS.NET. The contained object itself is exposed through the property
belonging to the value of this property: so if the
DataContainerType is set to entity collection, an entity collection is inside the
LLBLGenProDataSource and the
entity collection property is valid, though when
DataContainerType is set to
TypedList, a TypedList object is contained in the
LLBLGenProDataSource control.
The
GroupBy property is supported in TypedList/TypedView scenario's while PrefetchPath objects
(settable through the
PrefetchPathToUse property) are supported in entity collection scenarios.
Caching of data.
The data contained by the
LLBLGenProDataSource control is cached
in-between post-backs, until the data has to be refreshed. If caching is
enabled (default), the place where this data is cached is either in the
ViewState (default), ASP.NET cache or the Session. You can control where the
data is cached by setting the
LLBLGenProDataSource control's property
CacheLocation. You can disable this caching by setting the
CacheLocation property
to
None. If
CacheLocation is
set to Session, the data is stored in the session object with a key with the
following name:
__LLBLGENPRODATASOURCEDATA_controlUniqueID_BindingContainerName
ControlUniqueID is the UniqueID of the DataSource control on the page.
BindingContainerName is the name of the container the control is located in. This key is stored in the control state and is always preserved.
If the
CacheLocation is set to ASPNetCache, the data is stored in the ASP.NET Cache using the following key:
__LLBLGENPRODATASOURCEDATA_Guid
where the
Guid is a new Guid per
LLBLGenProDataSource control
instance. You can control the ASP.NET Cache duration as well by using the
property
ASPNetCacheDuration which indicates in minutes the time the
cached data should stay in the ASP.NET cache. Default is 20 minutes.
Disabling caching, by setting it to DataSourceCacheLocation.None, has
the effect that if the
LLBLGenProDataSource control is forced to
fetch data by a call to
ExecuteSelect, it always will refetch the
data from the database. This can lead to different data in the page between
post-backs (pre post-back and post post-back), so you should be aware of
this when using the None setting. As no data is cached, a bound control
should use the data in a read-only fashion. When
CacheLocation is set
to None, the
LLBLGenProDataSource control will still cache its own
state in the ASP.NET control state.
Setting the data container manually.
The controls offer properties (EntityCollection, TypedList, TypedView) to set the contained object to an external object, for example an entity collection
object you've fetched in a method in your business logic tier. This also offers the ability to for example bind
myCustomer.Orders to grids through the datasource controls by simply setting the property EntityCollection in the code behind file of the webform. You can do
this too with TypedLists by setting the TypedList property and with TypedViews by setting the TypedView property. Be sure to first set the
DataContainerType
property to the right container type, i.e. EntityCollection, TypedList or TypedView.
Two way databinding.
Two way databinding can be done with the
DataContainerType set to
EntityCollection. This means the
LLBLGenProDataSource control manages not only the
binding of data to a control but also the manipulation of data through the bound control (e.g. a GridView) of the data in the contained entity collection. As
TypedList and
TypedView classes are read-only by definition, you can't manipulate data inside these classes through the
LLBLGenProDataSource control. How the
LLBLGenProDataSource control fetches data (automatically or through code placed inside an eventhandler) as well as how it saves data (automatically or through
event handlers) is discussed in the next section.
LivePersistence and events
A boolean property of the
LLBLGenProDataSource control, called
LivePersistence, is used to signal the
LLBLGenProDataSource control
to perform the select, insert, update and delete actions directly on the database (true) or modify the entity collection and add the actions to a UnitOfWork
object (false).
If
LivePersistence is set to false, fetching data and saving data isn't performed by the
LLBLGenProDataSource control but an event is raised instead which passes an event arguments object which contains the parameters for the fetch or save and allows own code to perform the fetch or save. In any case,
the changed event is raised so the bound control(s) can refetch the data from the
LLBLGenProDataSource control.
LivePersistence causes 3 events to be raised:
- PerformSelect. This event is raised when the LLBLGenProDataSource control needs to retrieve data from the database. Use the passed-in PerformSelectEventArgs object to perform the Fetch action. You should fetch the data into the appropriate object inside the PerformSelectEventArgs object, for example the ContainedCollection using the parameters available in the PerformSelectEventArgs object.
- PerformGetDbCount. This event is raised when the LLBLGenProDataSource control needs to retrieve the number of items in the complete
resultset. This event is raised when server side paging is enabled and the total number of items in the resultset is required by the bound control(s). Your handler should fetch the count of the set to fetch by using the passed in PerformGetDbCountEventArgs object which contains all information necessary for the retrieval of the count value. Set the DbCount property of the PerformGetDbCountEventArgs object to the value read from the database. Be sure to pass to the PerformGetDbCountEventArgs.ContainedObjectToFetch.GetDbCount call the filter, prefetch path, sort expression and other objects available to you via the passed-in PerformGetDbCountEventArgs object. For ContainedObjectToFetch you should either use the property ContainedCollection, ContainedTypedList or ContainedTypedView, based on the container the datasource control works on. This is determinable by reading the PerformGetDbCountEventArgs.DataContainerType property in your handler.
- PerformWork. This event is raised when ExecuteInsert/Update/Delete is called on the LLBLGenProDataSource control by a bound control.
Typically this is done after an entity is edited in a GridView or FormView control for example, or a new entity is added through a bound control.
The work is tracked in a UnitOfWork object which is available to you in the passed in PerformWorkEventArgs object.
When a refetch of the data has taken place, the UnitOfWork object contained in the control is cleared. This means that any update/insert/delete work pending has
to be completed by that point.
Please examine the events and special event argument classes in the LLBLGen Pro
Reference manual.
Refetch
To ensure fresh data from the database. is retrieved, a flag on the
LLBLGenProDataSource
control called
Refetch can be set to true, so the DefaultView
will refetch the data, even if for example the page number is the same. This can be necessary if the code-behind code decides the data represented by the
LLBLGenProDataSource control is invalidated and has to be refetched from the database.
Using the LLBLGenProDataSource control.
Binding a
LLBLGenProDataSource control works like any other web form
DataSourceControl: just add the ID as DataSourceID in the bound control's
HTML, or select the
LLBLGenProDataSource control from the dropdown
box for available datasources in the bound control's smart-tag. The designer
of the
LLBLGenProDataSource control will allow the user to select the
DataContainerType and the type of object needed for the container (factory,
typedlist or typedview type).
By default no filter is set, no
groupby, no prefetch path, no sorting. To set a filter, prefetch path or
sort expression, a code behind page is required to set these parameters.
This is due to the requirement that these are compile time checked. You can
however also produce filters at runtime by using the ASP.NET parameter
binding feature. This allows you to setup a binding between a control (or
cookie, form etc.) which produces a value and the datasource control so the
value produced by the other control is used for filtering. See the example
below which uses two drop down boxes to create a filter at runtime for
fetching data.
Paging is supported as well: if you want server-side
paging, define the paging parameters on the
LLBLGenProDataSource2 in
the VS.NET property grid. If you want paging inside your bound control
(client-side paging), define the paging parameters in the bound control,
e.g. the GridView. To be able to work with paging, you of course have to
enable paging on the bound control.
The PerformWork event in an AJAX environment
When you use a grid like the DevExpress ASPxGrid for .NET, you can have all
edit activities on the client side, using AJAX communication with the
server. When you've setup the grid to be used on the client side, and the
LLBLGenProDataSource control has
LivePersistence set to false,
the changes made to the data on the client will be performed in one go when
the page gets a post-back. In this scenario, it's more efficient not to bind
to
PerformWork, but to place a button on the form which simply
performs the 'save', e.g. it says "Save changes". By not binding to the
PerformWork event, all ExecuteInsert/Update/Delete actions will take
place on the data, but aren't propagated to the database just yet, because
LivePersistence is set to false. In the button handler of your save
button, you then retrieve the UnitOfWork2 object from the
LLBLGenProDataSource control from the property
UnitOfWorkObject,
which contains all changes made and you can commit the changes in one
transaction.
Filtering on the fly
The
LLBLGenProDataSource control supports filtering on the fly based
on parameters specified which can retrieve values from other controls,
forms, cookies or other objects supported by the SelectParameters feature of
ASP.NET. This is available in a
LLBLGenProDataSource control via its
SelectParameters property. The
SelectParameters property
follows the same specification as the ObjectDataSource and are specified
declaratively using the <SelectParameters> HTML elements inside a
LLBLGenProDataSource control declaration. You can also use the VS.NET
designer for setting up the
SelectParameters, to do that simply click
the [...] button next to
SelectParameters in the Property grid of
VS.NET. Be sure that the parameter name has the
same name as a field
in the entity, typed list row or typed view row. You can't use
SelectParameters to build a filter on non-entity fields as it builds a
filter for the next fetch.
Trapping invalid input values
As the
LLBLGenProDataSource control is the receiver of the data
filled into a form, grid or other bound control, it can be these values are
invalid, for example they don't match the type of the entity field or they
are too big in size. By default, the
LLBLGenProDataSource control
will ignore these values and won't throw an exception. To make the control
throw an exception after all values have been evaluated, you can set the
LLBLGenProDataSource property
ThrowExceptionOnIllegalFieldInput
to true, which signals the control to throw an exception if one or more
fields received an illegal value which wasn't convertible to the type of the
field in an update/insert scenario. If set to true all illegal values are
collected and added to one single
ORMValueTypeMismatchException so
your code will receive just one exception to handle them all. If set to
false, the illegal values are ignored and the fields don't get set to a new
value.
Usage examples
Below are two examples: one example using LivePersistence set to true and one using LivePersistence set to false. They're basicly the same form. For VB.NET users: the HTML is for C#, you've to change the first line of the given HTML snippets into the following line to use it with VB.NET:
<%@ Page Language="VB" AutoEventWireup="true" CodeFile="Default.aspx.vb" Inherits="_Default" %>
Example using LivePersistence
This example contains a
form, which filters a list of Order entities, provided by the LLBLGenProDataSource control
orderDS, on the OrderEntity field
ShippingCountry, provided by a static drop down box, and a drop down box with all customers from Northwind, provided by LLBLGenProDataSource control
customerDS. Using parameter binding the two dropdown boxes produce filter information at runtime to produce the proper order list. No code required,
it's completely declarative HTML.
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<%@ Register Assembly="SD.LLBLGen.Pro.ORMSupportClasses.Web"
Namespace="SD.LLBLGen.Pro.ORMSupportClasses" TagPrefix="llblgenpro" %>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
All customers:<br />
Customers:
<asp:DropDownList ID="DropDownList1" runat="server" DataSourceID="customerDS"
DataTextField="CompanyName" DataValueField="CustomerId" AutoPostBack="True">
</asp:DropDownList><br />
ShipCountry:
<asp:DropDownList ID="DropDownList2" runat="server" AutoPostBack="True">
<asp:ListItem>Spain</asp:ListItem>
<asp:ListItem>Germany</asp:ListItem>
</asp:DropDownList><br />
<llblgenpro:llblgenprodatasource id="customerDS" runat="server"
cachelocation="Session" datacontainertype="EntityCollection" enablepaging="True"
livepersistence="True" entitycollectiontypename="NW20.CollectionClasses.CustomerCollection, NW20">
</llblgenpro:llblgenprodatasource>
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataSourceID="orderDS"
DataKeyNames="OrderId" AllowPaging="True" PageSize="5">
<Columns>
<asp:CommandField ShowDeleteButton="True" ShowEditButton="True" />
<asp:BoundField DataField="ShipAddress" HeaderText="ShipAddress" SortExpression="ShipAddress" />
<asp:BoundField DataField="ShipName" HeaderText="ShipName" SortExpression="ShipName" />
<asp:BoundField DataField="ShipCountry" HeaderText="ShipCountry" SortExpression="ShipCountry" />
<asp:BoundField DataField="CustomerId" HeaderText="CustomerId" SortExpression="CustomerId" />
<asp:BoundField DataField="ShipRegion" HeaderText="ShipRegion" SortExpression="ShipRegion" />
<asp:BoundField DataField="ShipCity" HeaderText="ShipCity" SortExpression="ShipCity" />
<asp:BoundField DataField="OrderId" HeaderText="OrderId" SortExpression="OrderId" />
<asp:BoundField DataField="ShipPostalCode" HeaderText="ShipPostalCode" SortExpression="ShipPostalCode" />
</Columns>
</asp:GridView>
<llblgenpro:llblgenprodatasource id="orderDS" runat="server" cachelocation="Session"
datacontainertype="EntityCollection" enablepaging="True"
entitycollectiontypename="NW20.CollectionClasses.OrderCollection, NW20" livepersistence="True">
<SelectParameters>
<asp:ControlParameter ControlID="DropDownList1" Name="CustomerId"
PropertyName="SelectedValue" Type="String" />
<asp:ControlParameter ControlID="DropDownList2" Name="ShipCountry"
PropertyName="SelectedValue" Type="String" />
</SelectParameters>
</llblgenpro:llblgenprodatasource>
</form>
</body>
</html>
Example using Perform Event handlers
The following example is the same form as in the previous example, with the same functionality, however now it uses
LivePersistence set to false, which means we've to perform the persistence logic ourselves by writing event handlers. The HTML is shown first, which is roughly the same as the previous example's HTML except it defines bindings to EventHandlers for PerformGetDbCount, PerformSelect and PerformWork. After that the code behind in VB.NET and C# is shown.
HTML page
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<%@ Register Assembly="SD.LLBLGen.Pro.ORMSupportClasses.Web"
Namespace="SD.LLBLGen.Pro.ORMSupportClasses" TagPrefix="llblgenpro" %>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
All customers:<br />
Customers:
<asp:DropDownList ID="DropDownList1" runat="server" DataSourceID="customerDS"
DataTextField="CompanyName" DataValueField="CustomerId" AutoPostBack="True">
</asp:DropDownList><br />
ShipCountry:
<asp:DropDownList ID="DropDownList2" runat="server" AutoPostBack="True">
<asp:ListItem>Spain</asp:ListItem>
<asp:ListItem>Germany</asp:ListItem>
</asp:DropDownList><br />
<llblgenpro:llblgenprodatasource id="customerDS" runat="server"
cachelocation="Session" datacontainertype="EntityCollection" enablepaging="True"
livepersistence="False" entitycollectiontypename="NW20.CollectionClasses.CustomerCollection, NW20"
OnPerformSelect="customerDS_PerformSelect">
</llblgenpro:llblgenprodatasource>
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataSourceID="orderDS"
DataKeyNames="OrderId" AllowPaging="True" PageSize="5">
<Columns>
<asp:CommandField ShowDeleteButton="True" ShowEditButton="True" />
<asp:BoundField DataField="ShipAddress" HeaderText="ShipAddress" SortExpression="ShipAddress" />
<asp:BoundField DataField="ShipName" HeaderText="ShipName" SortExpression="ShipName" />
<asp:BoundField DataField="ShipCountry" HeaderText="ShipCountry" SortExpression="ShipCountry" />
<asp:BoundField DataField="CustomerId" HeaderText="CustomerId" SortExpression="CustomerId" />
<asp:BoundField DataField="ShipRegion" HeaderText="ShipRegion" SortExpression="ShipRegion" />
<asp:BoundField DataField="ShipCity" HeaderText="ShipCity" SortExpression="ShipCity" />
<asp:BoundField DataField="OrderId" HeaderText="OrderId" SortExpression="OrderId" />
<asp:BoundField DataField="ShipPostalCode" HeaderText="ShipPostalCode" SortExpression="ShipPostalCode" />
</Columns>
</asp:GridView>
<llblgenpro:llblgenprodatasource id="orderDS" runat="server" cachelocation="Session"
datacontainertype="EntityCollection" enablepaging="True"
entitycollectiontypename="NW20.CollectionClasses.OrderCollection, NW20" livepersistence="False"
OnPerformSelect="orderDS_PerformSelect" OnPerformGetDbCount="orderDS_PerformGetDbCount"
OnPerformWork="orderDS_PerformWork">
<SelectParameters>
<asp:ControlParameter ControlID="DropDownList1" Name="CustomerId"
PropertyName="SelectedValue" Type="String" />
<asp:ControlParameter ControlID="DropDownList2" Name="ShipCountry"
PropertyName="SelectedValue" Type="String" />
</SelectParameters>
</llblgenpro:llblgenprodatasource>
</form>
</body>
</html>
Code behind
// C#
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using SD.LLBLGen.Pro.ORMSupportClasses;
using NW20.HelperClasses;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void customerDS_PerformSelect(object sender, PerformSelectEventArgs e)
{
// fetch all customers using the information passed in via the
// PerformSelectEventArgs object. This select doesn't have to perform any paging, as the
// data is for a combo box.
e.ContainedCollection.GetMulti(e.Filter, e.MaxNumberOfItemsToReturn, e.Sorter,
e.Relations, e.PrefetchPath);
}
protected void orderDS_PerformSelect(object sender, PerformSelectEventArgs e)
{
// fetch all orders which are in the selected page using the filter passed in
// via the PerformSelectEventArgs object.
e.ContainedCollection.GetMulti(e.Filter, e.MaxNumberOfItemsToReturn, e.Sorter,
e.Relations, e.PrefetchPath, e.PageNumber, e.PageSize);
}
protected void orderDS_PerformGetDbCount(object sender, PerformGetDbCountEventArgs e)
{
// get the total number of orders which match the filter passed in via the
// PerformGetDbCountEventArgs.
e.DbCount = e.ContainedCollection.GetDbCount(e.Filter, e.Relations);
}
protected void orderDS_PerformWork(object sender, PerformWorkEventArgs e)
{
// Perform the work passed in via the PerformWorkEventArgs object.
// Start a new transaction with the passed in unit of work.
using(Transaction trans = new Transaction(IsolationLevel.ReadCommitted, "PerformWork"))
{
// pass the transaction to the Commit routine and tell it to autocommit
// when the work is done. If an exception is thrown, the transaction will
// be rolled back by the Dispose call of the using statement.
e.Uow.Commit(trans, true);
}
}
}
' VB.NET
Imports SD.LLBLGen.Pro.ORMSupportClasses
Imports NW20.HelperClasses
Partial Class _Default
Inherits System.Web.UI.Page
Protected Sub customerDS_PerformSelect(ByVal sender As Object, ByVal e As PerformSelectEventArgs) _
Handles customerDS.PerformSelect
' fetch all customers using the information passed in via the
' PerformSelectEventArgs object. This select doesn't have to perform any paging, as the
' data is for a combo box.
e.ContainedCollection.GetMulti(e.Filter, e.MaxNumberOfItemsToReturn, e.Sorter, _
e.Relations, e.PrefetchPath)
End Sub
Protected Sub orderDS_PerformGetDbCount(ByVal sender As Object, ByVal e As PerformGetDbCountEventArgs) _
Handles orderDS.PerformGetDbCount
' get the total number of orders which match the filter passed in via the
' PerformGetDbCountEventArgs.
e.DbCount = e.ContainedCollection.GetDbCount(e.Filter, e.Relations)
End Sub
Protected Sub orderDS_PerformSelect(ByVal sender As Object, ByVal e As PerformSelectEventArgs) _
Handles orderDS.PerformSelect
' fetch all orders which are in the selected page using the filter passed in
' via the PerformSelectEventArgs object.
e.ContainedCollection.GetMulti(e.Filter, e.MaxNumberOfItemsToReturn, e.Sorter, _
e.Relations, e.PrefetchPath, e.PageNumber, e.PageSize)
End Sub
Protected Sub orderDS_PerformWork(ByVal sender As Object, ByVal e As PerformWorkEventArgs) _
Handles orderDS.PerformWork
' Perform the work passed in via the PerformWorkEventArgs object.
' Start a new transaction with the passed in unit of work.
Using trans As New Transaction(IsolationLevel.ReadCommitted, "PerformWork")
' pass the transaction to the Commit routine and tell it to autocommit
' when the work is done. If an exception is thrown, the transaction will
' be rolled back by the Dispose call of the using statement.
e.Uow.Commit(trans, True)
End Using
End Sub
End Class
Setting values for insert/update using bound parameters
ASP.NET supports bound parameters, where you can define parameters which
retrieve the values from other controls, cookies, query string etc. One
example is given above, using filtering based on the
SelectParameters.
The
LLBLGenProDataSource control supports also
InsertParameters
and
UpdateParameters. You can define these parameters for insert
(saving a new entity) and update (saving a changed entity) resp. the same
way as you do with
SelectParameters.
This way you can for
example set the 'EmployeeId' on a new order entity where you retrieve the
EmployeeId from a dropdown control. The value retrieved through a parameter
overrules a set value through the bound control. If no value is passed in by
the bound control and it's available through the
InsertParameters
(when inserting) or
UpdateParameters (when updating), the value in
the Insert/UpdateParameters collection is chosen.
Converting empty string values ("") to NULL values for inserts/updates
In a web-application, form values which are empty are represented as an
empty string (""). When an entity is edited through a form, it can be some
textboxes or other controls bound to fields of the entity are left empty /
point to an empty value: "". The
LLBLGenProDataSource2 control will
convert "" into NULL for all fields which .NET type isn't the string type.
If the field
is the string type, this can give a problem: what if the
empty string is a valid value?
To tell the
LLBLGenProDataSource
control that a field should get the empty string as a valid value
instead of NULL, you have to pass a List<string> object with all the
fieldnames of the fields which should accept "" as the valid value to the
property
FieldNamesKeepEmptyStringAsValue of the
LLBLGenProDataSource control. You should do this in the code behind of
your webform.
Example
// C#
// in your Page Load handler routine
if( !Page.IsPostBack )
{
List<string> fieldsWhichShouldKeepEmptyString = new List<string>();
fieldsWhichShouldKeepEmptyString.Add( "ShipAddress" );
_ordersDS.FieldNamesKeepEmptyStringAsValue = fieldsWhichShouldKeepEmptyString;
}
' VB.NET
' in your Page Load handler routine
If Not Page.IsPostBack Then
Dim fieldsWhichShouldKeepEmptyString As New List(Of String)()
fieldsWhichShouldKeepEmptyString.Add( "ShipAddress" )
_ordersDS.FieldNamesKeepEmptyStringAsValue = fieldsWhichShouldKeepEmptyString
End If
This example tells the LLBLGenProDataSource control called '_ordersDS' that the field
ShipAddress should get the value "" instead of NULL
if the form value is "" for that field.
Normally you don't need to set the property
FieldNamesKeepEmptyStringAsValue, if "" is not used for string values and NULL is acceptable instead.
It can be that the list of names which keep the empty string as the value is actually the complete set of fields of the entity. In that case, you can set the property
AllFieldsKeepEmptyStringAsValue to true, which makes the
LLBLGenProDataSource control to simply not convert empty strings to NULL values for entity fields. Setting this property to true will make
LLBLGenProDataSource control to ignore
FieldNamesKeepEmptyStringAsValue.
The SortingMode property
The
LLBLGenProDataSource control is capable to apply sorting when data has to be fetched, or for example when you've clicked a column header in a
bound GridView control. By default, the
LLBLGenProDataSource control sorts on the server-side, by producing a SortExpression which is then used by the fetch
logic. Which SortExpression is used depends on the value of the property
SorterToUse
of the
LLBLGenProDataSource control and the columns specified
by the bound control (e.g. clicked column header). It's possible to tell the LLBLGenProDataSource control to sort on the
client-side instead. Do
this by setting the LLBLGenProDataSource property
SortingMode.
By default it's set to ServerSide. If you set it to ClientSide, sorting is applied after the fetch, by sorting the DefaultView object of the
datasourcecontrol.
Server-side sorting only uses EntityField objects, so if the entity has a field which isn't a field mapped onto a table/view field, it's ignored in the
server-side sorting actions because it's not part of the query send to the database. This is also true for fields mapped onto related fields. In these
situations, use client-side sorting.
Be aware that if the
CacheLocation is set to None, the
LLBLGenProDataSource
control always has to fetch the data from the database again, as it can't sort cached data in-memory. If you want to avoid the roundtrip to the database, set the CacheLocation to another value than None.